package encaps.utils.rendering;

import encaps.action.Action;
import encaps.action.LoginAction;
import encaps.action.LogoutAction;
import encaps.action.ShowRegistrationPageAction;
import encaps.entities.Grant;
import encaps.entities.UserLocal;
import encaps.entities.UserLocalHome;
import encaps.resources.ActionFactories;
import encaps.resources.Config;
import encaps.resources.Image;
import encaps.resources.Labels;
import encaps.security.RoleManager;
import encaps.utils.*;
import static encaps.utils.html.HTML.*;
import encaps.utils.html.HTMLElement;
import encaps.utils.html.HTMLTableElement;
import encaps.utils.html.Styles;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.ejb.FinderException;
import javax.naming.NamingException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class SideBarBuilder {

    private List<ActionGrantPair> userActions;

    private static class ActionGrantPair {

        private String actionName;
        private Grant grant;

        public ActionGrantPair(String actionName, Grant grant) {
            this.actionName = actionName;
            this.grant = grant;
        }

        public String getActionName() {
            return actionName;
        }

        public Grant getGrant() {
            return grant;
        }
    }

    public SideBarBuilder() throws InitializationException {
        try {
            //Загружаем xml-файл как ресурс
            Class c = getClass();
            InputStream in = c.getResourceAsStream(ActionFactories.CONFIGURATION_FILE_PATH);

            //Парсим xml-файл
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(in);
            Element root = doc.getRootElement();

            //Заполнение списка пользовательских действий
            List factories = root.getChild(ActionFactories.FACTORY_LIST).getChildren(ActionFactories.FACTORY);
            userActions = new ArrayList<ActionGrantPair>(7);
            for (Object obj : factories) {
                Element factoryElement = (Element) obj;
                boolean isUserAction = factoryElement.getAttribute(ActionFactories.USER_ACTION).getBooleanValue();
                if (isUserAction) {
                    String actionName = factoryElement.getChild(ActionFactories.NAME).getValue().trim();
                    String requiredGrantName = factoryElement.getChild(ActionFactories.GRANT).getValue().trim();
                    Grant requiredGrant;
                    if (StringUtil.isEmpty(requiredGrantName)) {
                        requiredGrant = null;
                    } else {
                        requiredGrant = new Grant(requiredGrantName);
                    }
                    ActionGrantPair actionGrant = new ActionGrantPair(actionName, requiredGrant);
                    userActions.add(actionGrant);
                }
            }
        } catch (JDOMException ex) {
            throw new InitializationException(Labels.getLabel(Labels.SIDE_BUILDER_INSTANTATION_ERROR_MESSAGE), ex);
        } catch (IOException ex) {
            throw new InitializationException(Labels.getLabel(Labels.SIDE_BUILDER_INSTANTATION_ERROR_MESSAGE), ex);
        }
    }

    public String createSideBar(String userLogin) throws SystemException {

        StringBuilder sb = new StringBuilder();
        if (StringUtil.isEmpty(userLogin)) {
            return createGuestUserSection();
        } else {
            try {
                UserLocalHome userHome = EntityUtil.getUserHome();
                UserLocal user = userHome.findByLogin(userLogin);

                return createLoggedUserSection(user);
            } catch (NamingException ex) {
                throw new SystemException(Labels.getLabel(Labels.CANNOT_FIND_LOCAL_HOME_OBJECT_MESSAGE), ex);
            } catch (FinderException ex) {
                String message = String.format(Labels.getLabel(Labels.USER_NOT_FOUND_MESSAGE_PATTERN), userLogin);
                throw new SystemException(message, ex);
            }
        }
    }

    private String createLoggedUserSection(UserLocal user) throws DataAccessException {
        HTMLElement form = new HTMLElement(FORM);

        //Строка приветствия с кнопкой выхода:
        HTMLElement greetings = new HTMLElement(P);
        greetings.addAttribute(CLASS, Styles.GREETINGS);
        form.addContent(Labels.getLabel(Labels.GREETINGS) + user.getLogin());
        form.addContent(greetings);


        HTMLElement logoutButton = HTMLElement.createImageButton(Action.ACTION, LogoutAction.LOGOUT, Image.getImage(Image.LOGOUT));
        form.addContent(logoutButton);
        form.addContent(new HTMLElement(BR));
        form.addContent(new HTMLElement(BR));

        Collection<Grant> grants = getGrantsOfRole(user.getRole());
        for (ActionGrantPair action : userActions) {
            if (grants.contains(action.getGrant())) {
                HTMLElement p = new HTMLElement(P);
                p.addAttribute(CLASS, Styles.ACTION_LINK);
                HTMLElement link = new HTMLElement(A);
                String href = String.format("%s?%s=%s", Config.getHomePage(), Action.ACTION, action.getActionName());
                link.addAttribute(HREF, href);
                HTMLElement image = new HTMLElement(IMG);
                image.addAttribute(SRC, String.format("%s?%s=%s",
                        ImageServlet.IMAGE_SERVLET_NAME, ImageServlet.PATH, Image.getImage(action.getActionName())));
                image.addAttribute(ALT, Labels.getLabel(action.getActionName()));
                link.addContent(image);
                p.addContent(link);
                form.addContent(p);
            }
        }
        return form.toString();
    }

    private String createGuestUserSection() {
        HTMLElement form = new HTMLElement(FORM);
        form.addAttribute(ENCTYPE, MULTIPART_FORM_DATA);
        form.addAttribute(METHOD, POST);
        HTMLTableElement table = new HTMLTableElement(3, 2, false);
        table.addContentToCell(0, 0, Labels.getLabel(Labels.LOGIN) + ": ");
        HTMLElement loginInput = new HTMLElement(INPUT);
        loginInput.addAttribute(TYPE, TEXT);
        loginInput.addAttribute(NAME, LoginAction.LOGIN_FIELD);
        loginInput.addAttribute(SIZE, SIDEBAR_INPUT_SIZE);
        table.addContentToCell(0, 1, loginInput);
        table.addContentToCell(1, 0, Labels.getLabel(Labels.PASSWORD) + ": ");
        HTMLElement passwordInput = new HTMLElement(INPUT);
        passwordInput.addAttribute(TYPE, PASSWORD);
        passwordInput.addAttribute(NAME, LoginAction.PASSWORD_FIELD);
        passwordInput.addAttribute(SIZE, SIDEBAR_INPUT_SIZE);
        table.addContentToCell(1, 1, passwordInput);
        form.addContent(table);

        HTMLElement loginButton = HTMLElement.createImageButton(Action.ACTION, LoginAction.LOGIN, Image.getImage(Image.LOGIN));
        table.addContentToCell(2, 0, loginButton);

        HTMLElement registerButton = HTMLElement.createImageButton(Action.ACTION, ShowRegistrationPageAction.SHOW_REGISTRATION_PAGE, Image.getImage(Image.REGISTRATION));
        table.addContentToCell(2, 1, registerButton);

        return form.toString();
    }

    private static Collection<Grant> getGrantsOfRole(String role) throws DataAccessException {
        try {
            return RoleManager.getRoleManager().getRole(role).getGrants();
        } catch (InitializationException ex) {
            throw new DataAccessException(ex);
        }
    }
}
